package com.css.fxfzypg.modules.baseData.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import com.alibaba.fastjson.JSONObject;
import com.css.fxfzypg.common.utils.CheckObjFields;
import com.css.fxfzypg.constants.FxfzConstants;
import com.css.fxfzypg.constants.YNEnum;
import com.css.fxfzypg.modules.baseData.entity.HistoricalSeismicDataVo;
import com.css.fxfzypg.modules.baseData.repository.HistoricalSeismicDataRepository;
import com.css.fxfzypg.modules.baseData.entity.HistoricalSeismicData;
import com.css.fxfzypg.modules.baseData.service.HistoricalSeismicDataService;
import com.css.fxfzypg.modules.baseData.queryParams.HistoricalSeismicDataQueryParams;
import com.css.fxfzypg.modules.baseData.vo.HistoricalSeismicDataVO;
import com.css.fxfzypg.modules.preassesstaskmanage.entity.PreAssessTaskEntity;
import com.css.fxfzypg.modules.preassesstaskmanage.repository.PreAssessTaskRepository;
import com.css.fxfzypg.util.*;
import com.css.fxfzypg.web.PlatformSessionContext;
import com.css.fxfzypg.zcpt.sys.entity.SUser;
import com.css.fxfzypg.zcpt.sys.service.SUserService;
import com.css.fxfzypg.zcpt.sys.service.SysRoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
@Slf4j
public class HistoricalSeismicDataServiceImpl implements HistoricalSeismicDataService {
    @Resource
    HistoricalSeismicDataRepository historicalSeismicDataRepository;

    @Autowired
    SysRoleService sysRoleService;

    @Autowired
    SUserService sUserService;

    @Autowired
    PreAssessTaskRepository preAssessTaskRepository;
    public static final String[] HSD_SINTENSITY_ARR = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"};

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateHistoricalSeismicData(HistoricalSeismicData historicalSeismicData) {
        try {
            historicalSeismicData.setUpdateTime(new Date());
            historicalSeismicData.setUpdateUser(PlatformSessionContext.getUserID());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");
            /*historicalSeismicData.setTextHsdTime(sdf.format(historicalSeismicData.getHsdTime()));*/
            Date hsdTime = historicalSeismicData.getHsdTime();
            if (PlatformObjectUtils.isEmpty(hsdTime)) {
                String textHsdTime = historicalSeismicData.getTextHsdTime();
                if (!isStringNum(textHsdTime.replace(".", ""))) {
                    if (!isContainLetter(textHsdTime)) {
                        StringBuilder str = new StringBuilder();
                        String[] split = textHsdTime.split("\\.");
                        for (int l = 0; l < split.length; l++) {
                            if (split[l].contains("－")) {
                                str.append(".01");
                            } else {
                                str.append("." + split[l]);
                            }
                        }
                        historicalSeismicData.setHsdTime(sdf.parse(str.substring(str.indexOf(".") + 1, str.length())));
                    } else {

                        historicalSeismicData.setHsdTime(sdf.parse("1.1.1"));

                    }
                } else {
                    historicalSeismicData.setHsdTime(sdf.parse(textHsdTime));
                }
            } else {
                historicalSeismicData.setTextHsdTime(sdf.format(hsdTime));
            }
            historicalSeismicDataRepository.updateHistoricalSeismicData(historicalSeismicData);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void saveHistoricalSeismicData(HistoricalSeismicData historicalSeismicData) {
        historicalSeismicData.setHsdId(UUIDGenerator.getUUID());
        historicalSeismicData.setHsdStatus(YNEnum.N.toString());
        historicalSeismicData.setCreateTime(new Date());
        historicalSeismicData.setCreateUser(PlatformSessionContext.getUserID());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");
        historicalSeismicData.setTextHsdTime(sdf.format(historicalSeismicData.getHsdTime()));
        String userJson = sUserService.getSUser(PlatformSessionContext.getUserID());
        SUser sUser = CreateGson.createGson().fromJson(userJson, SUser.class);
        historicalSeismicData.setCreateName(sUser.getUserName());
        historicalSeismicDataRepository.saveHistoricalSeismicData(historicalSeismicData);
    }

    public boolean isStringNum(String str) {
        if (str.length() == 0 || str == null)
            return false;
        for (int i = 0; i < str.length(); i++) {
            if (!Character.isDigit(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    public boolean isContainLetter(String str) {

        String regex = ".*[a-zA-Z]+.*";

        Matcher m = Pattern.compile(regex).matcher(str);

        return m.matches();

    }


    @Override
    public Map<String, Object> getAllHistoricalSeismicData(HistoricalSeismicDataQueryParams queryParams, int curPage, int pageSize) {
        return historicalSeismicDataRepository.getAllHistoricalSeismicDataParams(queryParams, curPage, pageSize);
    }

    @Override
    public HistoricalSeismicData getHistoricalSeismicDataById(String id) {
        HistoricalSeismicData historicalSeismicData = historicalSeismicDataRepository.getHistoricalSeismicDataById(id);
        return historicalSeismicData;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteHistoricalSeismicDatas(List<String> ids) {
        historicalSeismicDataRepository.deleteHistoricalSeismicDatasById(ids);
    }


    @Override
    public void exportExcel(HttpServletResponse response, HistoricalSeismicDataQueryParams queryParams) {
        //List<HistoricalSeismicData> list = historicalSeismicDataRepository.findFormDataListByParams(queryParams);
        List<HistoricalSeismicDataVo> list = historicalSeismicDataRepository.getVo(queryParams);
        if (list == null || list.size() <= 0) {
            throw new RuntimeException("数据为空,无法导出！");
        }
        try {
            EasyPoiExcelUtil.exportExcel(list, "历史地震信息统计", "历史地震信息", HistoricalSeismicDataVo.class, "历史地震信息", response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    @Transactional
    public String importExcel(MultipartFile file) {
        try {
            // 返回的消息
            StringBuilder returnMsg = new StringBuilder();
            // 导入的参数信息
            ImportParams params = new ImportParams();
            // 设置简析的第一行
            params.setTitleRows(0);
            params.setHeadRows(1);
            // 是否需要校验
            params.setNeedVerify(true);
            // 获取到Excel数据
            ExcelImportResult<HistoricalSeismicDataVO> result = ExcelImportUtil.importExcelMore(file.getInputStream(), HistoricalSeismicDataVO.class, params);

            if (result.isVerifyFail()) {
                // 校验返回失败行信息
                Iterator<HistoricalSeismicDataVO> iterator = result.getFailList().iterator();
                while (iterator.hasNext()) {
                    HistoricalSeismicDataVO historicalSeismicDataVO = iterator.next();
                    HistoricalSeismicData historicalSeismicData = new HistoricalSeismicData();
                    BeanUtils.copyProperties(historicalSeismicDataVO, historicalSeismicData);
                    if (CheckObjFields.isAllFieldNull(historicalSeismicData)) {
                        continue;
                    }
                    returnMsg.append("第" + historicalSeismicDataVO.getRowNum() + "行 " + historicalSeismicDataVO.getErrorMsg() + "<br/>");
                }
            }
            if (returnMsg.length() > 0) {
                return returnMsg.toString();
            }

            List<HistoricalSeismicDataVO> list = result.getList();
            for (HistoricalSeismicDataVO item : list) {
                if (PlatformObjectUtils.isNotEmpty(item.getHsdSintensity())){
                    if (!Arrays.asList(HSD_SINTENSITY_ARR).contains(item.getHsdSintensity())) {
                        returnMsg.append("第" + item.getRowNum() + "行,不符合规范！(I/II/III/IV/V/VI/VII/VIII/IX/X)<br/>");
                        return returnMsg.toString();
                    }
                }
                HistoricalSeismicData historicalSeismicData = new HistoricalSeismicData();
                historicalSeismicData.setHsdId(UUIDGenerator.getUUID());
                historicalSeismicData.setCreateUser(PlatformSessionContext.getUserID());
                historicalSeismicData.setCreateTime(new Date());
                historicalSeismicData.setHsdStatus(YNEnum.N.toString());
                BeanUtils.copyProperties(item, historicalSeismicData);
                String userJson = sUserService.getSUser(PlatformSessionContext.getUserID());
                SUser sUser = CreateGson.createGson().fromJson(userJson, SUser.class);
                historicalSeismicData.setCreateName(sUser.getUserName());
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");
                String textHsdTime = historicalSeismicData.getTextHsdTime();
                if (!isStringNum(textHsdTime.replace(".", ""))) {
                    if (!isContainLetter(textHsdTime)) {
                        StringBuilder str = new StringBuilder();
                        String[] split = textHsdTime.split("\\.");
                        for (int l = 0; l < split.length; l++) {
                            if (split[l].contains("－")) {
                                str.append(".01");
                            } else {
                                str.append("." + split[l]);
                            }
                        }
                        historicalSeismicData.setHsdTime(sdf.parse(str.substring(str.indexOf(".") + 1, str.length())));
                    } else {
                        historicalSeismicData.setHsdTime(sdf.parse("1.1.1"));
                    }
                } else {
                    historicalSeismicData.setHsdTime(sdf.parse(textHsdTime));
                }
                historicalSeismicDataRepository.saveHistoricalSeismicData(historicalSeismicData);
            }
            returnMsg.append("成功导入" + (result.getList().size()) + "条<br/>");

            return returnMsg.toString();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return "导入失败，请检查数据正确性";
        }

    }

    @Override
    public boolean isCouAdmin() {
        StringBuilder str = new StringBuilder("");
        String userId = PlatformSessionContext.getUserID();
       /* String user = sUserService.getSUser(userId);
        SUser sUser = CreateGson.createGson().fromJson(user, SUser.class);*/
        String role = sysRoleService.getRoleByUserId(userId);
        List<Map> roleMaps = JSONObject.parseArray(role, Map.class);
        for (Map roleMap : roleMaps) {
            str.append(roleMap.get("roleCode") + ",");
        }
        String roles = str.toString();
        if (roles.contains(FxfzConstants.YPG_COUN_GL_ROLE)) {
            return true;
        }
        return false;
    }

    @Override
    public List<HistoricalSeismicData> judgeHistoricalSeismicData(String taskId) {
        HistoricalSeismicDataQueryParams params = new HistoricalSeismicDataQueryParams();
        List<HistoricalSeismicData> formData = historicalSeismicDataRepository.findFormDataListByParams(params);
        List<HistoricalSeismicData> historicalSeismicDataList = new ArrayList<>();
        PreAssessTaskEntity preAssessTaskEntity = preAssessTaskRepository.findById(taskId);
        if (!PlatformObjectUtils.isEmpty(formData)) {
            if (!PlatformObjectUtils.isEmpty(preAssessTaskEntity)) {
                String taskRegion = preAssessTaskEntity.getTaskRegion();
                for (int i = 0; i < formData.size(); i++) {
                    BigDecimal hsdLongitude = formData.get(i).getHsdLongitude();
                    BigDecimal hsdLatitude = formData.get(i).getHsdLatitude();
                    if (!PlatformObjectUtils.isEmpty(hsdLongitude) && !PlatformObjectUtils.isEmpty(hsdLatitude)) {
                        //标记的调研点
                        Point point = new Point(hsdLongitude.doubleValue(), hsdLatitude.doubleValue());
                        Point[] points = new Point[0];
                        List<Point> pointList = new ArrayList<>(Arrays.asList(points));
                        if (!PlatformObjectUtils.isEmpty(taskRegion)) {
                            //判断该灾害风险点是否在任务区域中
                            boolean pointInPolygon = false;
                            if (taskRegion.indexOf("MULTIPOLYGON") != -1) {//判断是否为行政区划面
                                for (String region : taskRegion.split(";")) {//多个行政区划
                                    region = region.substring(region.indexOf("(((") + 3, region.lastIndexOf(")))"));
                                    region = region.replace(")), ((", "!");
                                    region = region.replace("), (", "#");
                                    if (region.contains("!")) {
                                        for (String geometries : region.split("!")) {//多面
                                            if (geometries.indexOf("#") != -1) {//判断是否存在镂空的面
                                                List<String> polygonList = Arrays.asList(geometries.split("#"));
                                                for (int m = 0; m < polygonList.size(); m++) {//是否存在镂空的面
                                                    String polygon = polygonList.get(m);
                                                    if (m == 0) {//第一个面
                                                        Point[] points1 = new Point[0];
                                                        List<Point> pointList1 = new ArrayList<>(Arrays.asList(points1));
                                                        for (String regionTemp : polygon.split(", ")) {
                                                            Double regionX = new Double(regionTemp.split(" ")[0].trim());
                                                            Double regionY = new Double(regionTemp.split(" ")[1].trim());
                                                            Point regionPoint = new Point(regionX, regionY);
                                                            //regionPoint.setLocation(regionX,regionY);
                                                            pointList1.add(regionPoint);
                                                        }
                                                        //任务中选中的区域
                                                        Point[] regionPointArr = pointList1.toArray(points1);
                                                        //判断该灾害风险点是否在任务区域中
                                                        pointInPolygon = AreaBoundaryUtil.isPointInPolygon(point, regionPointArr);
                                                        if (pointInPolygon) {
                                                            //继续判断是否在镂空面内
                                                            continue;
                                                        } else {
                                                            break;
                                                        }
                                                    } else {//镂空的面
                                                        Point[] points1 = new Point[0];
                                                        List<Point> pointList1 = new ArrayList<>(Arrays.asList(points1));
                                                        for (String regionTemp : polygon.split(", ")) {
                                                            Double regionX = new Double(regionTemp.split(" ")[0].trim());
                                                            Double regionY = new Double(regionTemp.split(" ")[1].trim());
                                                            Point regionPoint = new Point(regionX, regionY);
                                                            //regionPoint.setLocation(regionX,regionY);
                                                            pointList1.add(regionPoint);
                                                        }
                                                        //任务中选中的区域
                                                        Point[] regionPointArr = pointList1.toArray(points1);
                                                        //判断该灾害风险点是否在任务区域中
                                                        boolean tempBool = AreaBoundaryUtil.isPointInPolygon(point, regionPointArr);
                                                        if (tempBool) {//判断是否在镂空面内
                                                            pointInPolygon = false;//点在镂空面内，即点不在面内
                                                        }
                                                    }
                                                }

                                            } else {//正常的面
                                                Point[] points1 = new Point[0];
                                                List<Point> pointList1 = new ArrayList<>(Arrays.asList(points1));
                                                String polygon = geometries;
                                                for (String regionTemp : polygon.split(", ")) {
                                                    Double regionX = new Double(regionTemp.split(" ")[0].trim());
                                                    Double regionY = new Double(regionTemp.split(" ")[1].trim());
                                                    Point regionPoint = new Point(regionX, regionY);
                                                    //regionPoint.setLocation(regionX,regionY);
                                                    pointList1.add(regionPoint);
                                                }
                                                //任务中选中的区域
                                                Point[] regionPointArr = pointList1.toArray(points1);
                                                //判断该灾害风险点是否在任务区域中
                                                pointInPolygon = AreaBoundaryUtil.isPointInPolygon(point, regionPointArr);
                                                if (pointInPolygon) {
                                                    break;
                                                }
                                            }
                                        }
                                    } else {
                                        if (region.indexOf("#") != -1) {//判断是否存在镂空的面
                                            List<String> polygonList = Arrays.asList(region.split("#"));
                                            for (int m = 0; m < polygonList.size(); m++) {//是否存在镂空的面
                                                String polygon = polygonList.get(m);
                                                if (m == 0) {//第一个面
                                                    Point[] points1 = new Point[0];
                                                    List<Point> pointList1 = new ArrayList<>(Arrays.asList(points1));
                                                    for (String regionTemp : polygon.split(", ")) {
                                                        Double regionX = new Double(regionTemp.split(" ")[0].trim());
                                                        Double regionY = new Double(regionTemp.split(" ")[1].trim());
                                                        Point regionPoint = new Point(regionX, regionY);
                                                        //regionPoint.setLocation(regionX,regionY);
                                                        pointList1.add(regionPoint);
                                                    }
                                                    //任务中选中的区域
                                                    Point[] regionPointArr = pointList1.toArray(points1);
                                                    //判断该灾害风险点是否在任务区域中
                                                    pointInPolygon = AreaBoundaryUtil.isPointInPolygon(point, regionPointArr);
                                                    if (pointInPolygon) {
                                                        //继续判断是否在镂空面内
                                                        continue;
                                                    } else {
                                                        break;
                                                    }
                                                } else {//镂空的面
                                                    Point[] points1 = new Point[0];
                                                    List<Point> pointList1 = new ArrayList<>(Arrays.asList(points1));
                                                    for (String regionTemp : polygon.split(", ")) {
                                                        Double regionX = new Double(regionTemp.split(" ")[0].trim());
                                                        Double regionY = new Double(regionTemp.split(" ")[1].trim());
                                                        Point regionPoint = new Point(regionX, regionY);
                                                        //regionPoint.setLocation(regionX,regionY);
                                                        pointList1.add(regionPoint);
                                                    }
                                                    //任务中选中的区域
                                                    Point[] regionPointArr = pointList1.toArray(points1);
                                                    //判断该灾害风险点是否在任务区域中
                                                    boolean tempBool = AreaBoundaryUtil.isPointInPolygon(point, regionPointArr);
                                                    if (tempBool) {//判断是否在镂空面内
                                                        pointInPolygon = false;//点在镂空面内，即点不在面内
                                                    }
                                                }
                                            }

                                        } else {//正常的面
                                            Point[] points1 = new Point[0];
                                            List<Point> pointList1 = new ArrayList<>(Arrays.asList(points1));
                                            String polygon = region;
                                            for (String regionTemp : polygon.split(", ")) {
                                                Double regionX = new Double(regionTemp.split(" ")[0].trim());
                                                Double regionY = new Double(regionTemp.split(" ")[1].trim());
                                                Point regionPoint = new Point(regionX, regionY);
                                                //regionPoint.setLocation(regionX,regionY);
                                                pointList1.add(regionPoint);
                                            }
                                            //任务中选中的区域
                                            Point[] regionPointArr = pointList1.toArray(points1);
                                            //判断该灾害风险点是否在任务区域中
                                            pointInPolygon = AreaBoundaryUtil.isPointInPolygon(point, regionPointArr);
                                            if (pointInPolygon) {
                                                break;
                                            }
                                        }
                                    }
                                    if (pointInPolygon) {
                                        break;
                                    }
                                }
                            } else {//地图圈选面
                                for (String region : taskRegion.split(";")) {
                                    Double regionX = new Double(region.split(",")[0].trim());
                                    Double regionY = new Double(region.split(",")[1].trim());
                                    Point regionPoint = new Point(regionX, regionY);
                                    //regionPoint.setLocation(regionX,regionY);
                                    pointList.add(regionPoint);
                                }
                                //任务中选中的区域
                                Point[] regionPointArr = pointList.toArray(points);
                                //判断该灾害风险点是否在任务区域中
                                pointInPolygon = AreaBoundaryUtil.isPointInPolygon(point, regionPointArr);
                            }
                            //判断该灾害风险点是否在任务区域中
                            if (pointInPolygon) {
                                historicalSeismicDataList.add(formData.get(i));
                            }
                        }
                    }
                }
            }
        }


        return historicalSeismicDataList;
    }

    @Override
    public Integer countByCounty(String countyName) {
        return historicalSeismicDataRepository.countByCounty(countyName);
    }

    @Override
    public Integer countByCity(String cityName) {
        return historicalSeismicDataRepository.countByCity(cityName);
    }

    @Override
    public Integer countByProvince(String name) {
        return historicalSeismicDataRepository.countByProvince(name);
    }


}
